RK3568 引导
上面这个图中,某一时刻只会匹配一种方式启动方式,即选择从某个外设中加载程序,如果都没有则从 USB 中进行下载。至此,关于 SoC 引导,以及烧录的过程就有了一个大概的了解了。
Rockchip 引导
- 引导流程 1 是典型的使用 Rockchip miniloader 的 Rockchip 引导流程
- 引导流程 2 用于大多数 SoC,使用 U-Boot TPL 进行 DDR 初始化,使用 SPL 加载加载 u-boot.itb 文件
针对不同的解决方案,Rockchip 提供了两种不同的启动加载程序方法,其步骤和生成的镜像文件也是完全不同的。
- TPL/SPL加载:使用 Rockchip 官方提供的 TPL/SPL U-boot,该方式完全开源
- 官方固件加载:使用 Rockchip idbLoader,它由 Rockchip rkbin project 的 Rockchip ddr init bin 和 miniloader bin 组合而成,该方式不开源
Rockchip 处理器启动可以划分为5个阶段:
+--------+----------------+----------+-------------+---------+
| Boot | Terminology #1 | Actual | Rockchip | Image |
| stage | | program | Image | Location|
| number | | name | Name | (sector)|
+--------+----------------+----------+-------------+---------+
| 1 | Primary | ROM code | BootROM | |
| | Program | | | |
| | Loader | | | |
| | | | | |
| 2 | Secondary | U-Boot |idbloader.img| 0x40 | pre-loader
| | Program | TPL/SPL | | |
| | Loader (SPL) | | | |
| | | | | |
| 3 | - | U-Boot | u-boot.itb | 0x4000 | including u-boot and atf
| | | | uboot.img | | only used with miniloader
| | | | | |
| | | ATF/TEE | trust.img | 0x6000 | only used with miniloader
| | | | | |
| 4 | - | kernel | boot.img | 0x8000 |
| | | | | |
| 5 | - | rootfs | rootfs.img | 0x40000 |
+--------+----------------+----------+-------------+---------+
ATF (ARM Trust Firmware)
ATF 主要负责在启动 uboot 之前把 CPU 从安全的 EL3 切换到 EL2,然后跳转到 uboot,并且在内核启动后负责启动其他的 CPU。
ATF 将系统启动从最底层进行了完整的统一划分,将 secure monitor 的功能放到了 bl31 中进行,这样当系统完全启动之后,在 CA 或者 TEE OS 中触发了 smc
或者是其他的中断之后,首先是遍历注册到 bl31 中的对应的 service 来判定具体的 handle,这样可以对系统所有的关键 smc
或者是中断操作做统一的管理和分配。
AtomicPi-CA1 启动模式
在正点原子提供的 pdf 资料中,关于 rk3568 启动模式,有如下介绍
模式 | 是否支持烧录 | 说明 |
---|---|---|
Normal | × | 通过引导 rootfs 启动。加载 rootfs根文件系统,大多数的开发都是在这个模式下进行的。即,从外设中读取驱动程序。 |
Loader | ✓ | 可以通过烧写工具单独烧写某一个分区镜像文件。即,从 USB 中进行下载。 |
Maskrom | ✓ | Flash 在未烧录镜像时,芯片会引导进入 Maskrom 模式可以进行初次镜像的烧写;开发调试过程中若遇到无法正常进入 Loader 模式的情况,也可进入 Maskrom 模式烧写镜像。 |
提供的烧录工具:RKDevTool_Release_v2.92.zip
可以识别到连接的设备,并显示当前模式。
这里显示 5 个文件会被烧录:
地址 | 名字 | 大小 |
---|---|---|
0x00000000 | Loader | 447K |
0x00000000 | Parameter | 1K |
0x00004000 | uboot | 4M(4096K) |
0x00006000 | boot | 256MB(262144K) |
0x00086000 | rootfs | 3.69G |
我一开始以为它们是按照地址,以字节顺序存放,之后才反应过来,这里的地址应该是以扇区 (512 字节) 存放的。即,0 - 0x4000 是 0x4000 个扇区。
这里看看 Parameter,它是一个文本内容,应该是为烧录工具提供一些参数用的。
FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3568
MACHINE_ID: 007
MANUFACTURER: RK3568
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 0xffffffff
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00080000@0x00006000(boot),-@0x00086000(rootfs:grow)
uuid:rootfs=614e0000-0000-4b53-8000-1d28000054a9
-@0x00086000
这个的意思好像是 长度@起始地址(名称)
这样的格式,-
表示剩余所有空间。
所以,这里表示:
表示 | 起始地址 | 大小/扇区 | 标识 | 计算 |
---|---|---|---|---|
0x00002000@0x00004000(uboot) | 0x4000 | 0x2000 | uboot | (0x2000 * 512)/1024 = 0x1000K = 4096K |
0x00080000@0x00006000(boot) | 0x6000 | 0x80000 | boot | 0x80000 * 512)/1024 = 0x40000K = 262144K = 256M |
-@0x00086000(rootfs:grow) | 0x86000 | 剩余空间 | rootfs | - |
板子上的 eMMC 分区
运行 fdisk -l
以及 lsblk
root@atompi-ca1:/# sudo fdisk -l
Disk /dev/ram0: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/mmcblk0: 57.62 GiB, 61865984000 bytes, 120832000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 10350000-0000-4557-8000-315B000025D3
Device Start End Sectors Size Type
/dev/mmcblk0p1 16384 24575 8192 4M unknown
/dev/mmcblk0p2 24576 548863 524288 256M unknown
/dev/mmcblk0p3 548864 120831935 120283072 57.4G unknown
root@atompi-ca1:/# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
mmcblk0 179:0 0 57.6G 0 disk
├─mmcblk0p1 179:1 0 4M 0 part
├─mmcblk0p2 179:2 0 256M 0 part
└─mmcblk0p3 179:3 0 57.4G 0 part /
mmcblk0boot0 179:32 0 4M 1 disk
mmcblk0boot1 179:64 0 4M 1 disk
root@atompi-ca1:/# blkid /dev/mmcblk0p3
/dev/mmcblk0p3: UUID="ee146551-049e-4373-a624-00f25f63dd48" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="rootfs" PARTUUID="614e0000-0000-4b53-8000-1d28000054a9"
显而易见,/dev/mmcblk0p3
的 UUID 为 Parameter 最后一行,表示 rootfs 所在分区。mmcblk0 为 eMMC 物理分区中的 UDA (User Data Area) 分区,其烧录对应关系如下:
Device Start End Sectors Size Type
/dev/mmcblk0p1 16384(0x4000) 24575 8192 4M unknown uboot.img
/dev/mmcblk0p2 24576(0x6000) 548863 524288 256M unknown boot.img
/dev/mmcblk0p3 548864(0x86000) 120831935 120283072 57.4G unknown rootfs.img
那么 Loader 在哪里呢?
RKDevTool 显示的,也就是 config.cfg 中的 Loader,就是 MiniLoaderAll.bin,就是 rkxx_loader_vxxx.xxx.bin (正点原子提供的版本是: rk356x_spl_loader_v1.18.112.bin 闭源),被烧录到哪里去了呢?
我猜应该在 mmcblk0 开头的扇区中,通过 dd
拷贝出来与 MiniLoaderAll.bin 做对比,有些大块是相同的,所以我猜测虽然编译出来是 .bin 但还是是有格式的,之后在网上也看到相关博客说具有某种格式。
到这里,就清楚了。
rk3568 的 BootROM 将 MiniLoaderAll.bin 加载到 SRAM 中运行,由它负责后续加载 uboot。在这之前, BootROM 会检查 Bootstrap Pin 以确定如何进行引导,比如:
模式 | 操作进入 | uboot 命令进入 |
---|---|---|
Maskrom | UPDATA +上电复位 |
rbrom |
Loader | V+ +上电复位 |
download |
注意 : 先连接电源适配器和 OTG
后续有兴趣有时间,可以通过反汇编看 MiniLoaderAll.bin 是如何初始化硬件的并加载后续程序的 . . .
参考
- Rockchip RK3399 - 引导流程和准备工作
- Rockchip RK3568 TRM Part1 V1.1-20210301.pdf
- eMMC分区详解